package cn.geminis.crypto.core.key;

import cn.geminis.crypto.core.util.EncodeUtils;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PrivateKeyInfoFactory;

import java.io.IOException;
import java.util.Objects;

/**
 * @author Allen
 */
public class PrivateKey implements java.security.PrivateKey {

    private PrivateKeyInfo privateKey;
    private AsymmetricKeyParameter privateKeyParam;

    public PrivateKey(AsymmetricKeyParameter privateKey) {
        try {
            this.privateKeyParam = privateKey;
            this.privateKey = PrivateKeyInfoFactory.createPrivateKeyInfo(privateKey);
        } catch (IOException e) {
            throw new RuntimeException("解析私钥错误", e);
        }
    }

    public PrivateKey(byte[] data) {
        ASN1Encodable asn1 = EncodeUtils.fromDERorPEM(data);
        this.privateKey = PrivateKeyInfo.getInstance(asn1);
        if (this.privateKey == null) {
            throw new RuntimeException("该数据不是私钥数据，数据类型为：" + asn1.getClass());
        }
    }

    public PrivateKey(PrivateKeyInfo privateKey) {
        this.privateKey = privateKey;
    }

    @Override
    public String getAlgorithm() {
        return this.privateKey.getPrivateKeyAlgorithm().getAlgorithm().getId();
    }

    @Override
    public String getFormat() {
        return EncodeUtils.toPEM(this.privateKey);
    }

    @Override
    public byte[] getEncoded() {
        return EncodeUtils.toDER(this.privateKey);
    }

    public PrivateKeyInfo getPrivateKeyInfo() {
        return privateKey;
    }

    public AsymmetricKeyParameter getKeyParameter() {
        if (Objects.isNull(privateKeyParam)) {
            try {
                this.privateKeyParam = PrivateKeyFactory.createKey(this.privateKey);
            } catch (IOException e) {
                throw new RuntimeException("获取私钥参数错误", e);
            }
        }
        return this.privateKeyParam;
    }
}
